/*
 * SubSonic - http://subsonicproject.com
 * 
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an 
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Data;
using SubSonic.Utilities;

namespace SubSonic
{
    /// <summary>
    /// Summary for the DBCollection class
    /// </summary>
    public class DBCollection : List<DB>
    {
        /// <summary>
        /// Gets or sets the <see cref="SubSonic.DB"/> with the specified db name.
        /// </summary>
        /// <value></value>
        public DB this[string dbName]
        {
            get
            {
                foreach(DB db in this)
                {
                    if(Utility.IsMatch(db.ProviderName, dbName))
                        return db;
                }
                return null;
            }
            set
            {
                for(int index = 0; index < Count; index++)
                {
                    if(Utility.IsMatch(this[index].ProviderName, dbName))
                    {
                        this[index] = value;
                        break;
                    }
                }
            }
        }
    }

    /// <summary>
    /// Summary for the DB class
    /// </summary>
    public class DB
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DB"/> class.
        /// </summary>
        /// <param name="providerName">Name of the provider.</param>
        public DB(string providerName)
        {
            //load up the tables
            Tables = new TableSchema.TableCollection();
            Views = new TableSchema.TableCollection();

            _tables.AddRange(DataService.GetTables(providerName));
            _views.AddRange(DataService.GetViews(providerName));

            if(_sps == null)
                LoadStoredProcedures(providerName);
        }

        /// <summary>
        /// Loads the stored procedures.
        /// </summary>
        /// <param name="providerName">Name of the provider.</param>
        private void LoadStoredProcedures(string providerName)
        {
            //DataService.ResetDatabases();
            string[] sps = DataService.GetSPList(providerName);
            if(sps.Length > 0)
            {
                _sps = new List<StoredProcedure>();
                //System.Data.IDataReader rdr = null;
                DataProvider provider = DataService.Providers[providerName];
                foreach(string s in sps)
                {
                    if(String.IsNullOrEmpty(provider.SPStartsWith) || s.StartsWith(provider.SPStartsWith))
                    {
                        //declare the sp
                        StoredProcedure sp = new StoredProcedure(s, provider);

                        //get the params
                        IDataReader rdr = DataService.GetSPParams(s, providerName);
                        while(rdr.Read())
                        {
                            StoredProcedure.Parameter par = new StoredProcedure.Parameter();
                            par.DBType = DataService.GetDbType(rdr[SqlSchemaVariable.DATA_TYPE].ToString(), providerName);
                            string sMode = rdr[SqlSchemaVariable.MODE].ToString();
                            if(Utility.IsMatch(sMode, SqlSchemaVariable.MODE_INOUT))
                                par.Mode = ParameterDirection.InputOutput;

                            par.Name = rdr[SqlSchemaVariable.NAME].ToString();
                            par.QueryParameter = provider.MakeParam(par.Name);
                            par.DisplayName = Utility.GetParameterName(par.Name, provider);
                            sp.Parameters.Add(par);
                        }
                        rdr.Close();
                        _sps.Add(sp);
                    }
                }
            }
        }


        #region props

        private string _connectionString;
        private DataProvider _provider;

        private string _providerName;
        private List<StoredProcedure> _sps; // =new List<StoredProcedure>();
        private TableSchema.TableCollection _tables;
        private TableSchema.TableCollection _views;

        /// <summary>
        /// Gets or sets the connection string.
        /// </summary>
        /// <value>The connection string.</value>
        public string ConnectionString
        {
            get { return _connectionString; }
            set { _connectionString = value; }
        }

        /// <summary>
        /// Gets or sets the name of the provider.
        /// </summary>
        /// <value>The name of the provider.</value>
        public string ProviderName
        {
            get { return _providerName; }
            set { _providerName = value; }
        }

        /// <summary>
        /// Gets or sets the provider.
        /// </summary>
        /// <value>The provider.</value>
        public DataProvider Provider
        {
            get { return _provider; }
            set { _provider = value; }
        }

        /// <summary>
        /// Gets or sets the tables.
        /// </summary>
        /// <value>The tables.</value>
        public TableSchema.TableCollection Tables
        {
            get { return _tables; }
            set { _tables = value; }
        }

        /// <summary>
        /// Gets or sets the views.
        /// </summary>
        /// <value>The views.</value>
        public TableSchema.TableCollection Views
        {
            get { return _views; }
            set { _views = value; }
        }

        /// <summary>
        /// Gets or sets the stored procedures.
        /// </summary>
        /// <value>The stored procedures.</value>
        public List<StoredProcedure> StoredProcedures
        {
            get
            {
                if(_sps == null)
                    LoadStoredProcedures(ProviderName);

                return _sps;
            }
            set { _sps = value; }
        }

        #endregion
    }
}